package com.zq.widget.inverted.game.role.anim;

import android.animation.TypeEvaluator;
import android.graphics.PointF;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;

/**
 * Created by zhangqiang on 2018/3/29.
 */
public class AnimProxy<V> implements Anim<V> {

    public static AnimProxy<Number> ofFloat(Number startValue, Number endValue) {

        return new AnimProxy<>(startValue, endValue);
    }

    public static AnimProxy<Integer> ofInt(int startValue, int endValue) {

        return new AnimProxy<>(startValue, endValue);
    }

    public static AnimProxy<PointF> ofPointF(PointF startValue, PointF endValue) {

        return new AnimProxy<>(startValue, endValue);
    }

    private long startTime;
    private V animateValue;
    private V startValue, endValue;
    private long duration;
    private Interpolator interpolator;
    private TypeEvaluator<V> typeEvaluator;
    private OnAnimUpdateListener<V> onAnimUpdateListener;
    private int repeatCount = 1;
    private RepeatMode repeatMode = RepeatMode.RESTART;
    private int runIndex;

    public AnimProxy(V startValue, V endValue) {
        this.startValue = startValue;
        this.endValue = endValue;
    }

    @Override
    public boolean compute() {

        long timeMillis = AnimationUtils.currentAnimationTimeMillis();
        if (startTime <= 0) {
            startTime = timeMillis;
        }
        long pastTime = timeMillis - startTime;
        if (pastTime < duration) {

            float factor = (float) pastTime / duration;
            float interpolation = interpolator.getInterpolation(factor);
            if(runIndex % 2 == 1 && repeatMode == RepeatMode.REVERSE){
                animateValue = typeEvaluator.evaluate(interpolation, endValue, startValue);
            }else{
                animateValue = typeEvaluator.evaluate(interpolation, startValue, endValue);
            }
            if(onAnimUpdateListener != null){
                onAnimUpdateListener.onAnimUpdate(this);
            }
            return true;
        }else if(runIndex < repeatCount - 1){

            runIndex ++;
            startTime = timeMillis;
            return true;
        }else if(repeatCount == -1){

            runIndex ++;
            startTime = timeMillis;
            return true;
        }
        return false;
    }

    @Override
    public V getAnimateValue() {
        return animateValue;
    }

    public long getDuration() {
        return duration;
    }

    public AnimProxy<V> setDuration(long duration) {
        this.duration = duration;
        return this;
    }

    public Interpolator getInterpolator() {
        return interpolator;
    }

    public AnimProxy<V> setInterpolator(Interpolator interpolator) {
        this.interpolator = interpolator;
        return this;
    }

    public TypeEvaluator<V> getTypeEvaluator() {
        return typeEvaluator;
    }

    public AnimProxy<V> setTypeEvaluator(TypeEvaluator<V> typeEvaluator) {
        this.typeEvaluator = typeEvaluator;
        return this;
    }

    public OnAnimUpdateListener getOnAnimUpdateListener() {
        return onAnimUpdateListener;
    }

    public AnimProxy<V> setOnAnimUpdateListener(OnAnimUpdateListener<V> onAnimUpdateListener) {
        this.onAnimUpdateListener = onAnimUpdateListener;
        return this;
    }

    public int getRepeatCount() {
        return repeatCount;
    }

    public AnimProxy<V> setRepeatCount(int repeatCount) {
        this.repeatCount = repeatCount;
        return this;
    }

    public RepeatMode getRepeatMode() {
        return repeatMode;
    }

    public AnimProxy<V> setRepeatMode(RepeatMode repeatMode) {
        this.repeatMode = repeatMode;
        return this;
    }
}
